package com.example.serviceImpl;

import com.example.common.HttpStatus;
import com.example.common.HttpStatusDescriptions;
import com.example.common.ResponseResult;
import com.example.entity.User;
import com.example.exception.CustomLoginException;
import com.example.mapper.SysUserMapper;
import com.example.redis.RedisCache;
import com.example.redis.RedisKey;
import com.example.security.LoginUser;
import com.example.service.SysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author ccf@lijiaqiang
 * @since 2023-10-26
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, User> implements SysUserService {

    @Autowired
    private AuthenticationManager authentication;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private HttpStatusDescriptions httpStatusDescriptions;

    /**
     * 用户退出登录接口
     * @return 返回结果
     */
    @Override
    public ResponseResult<?> logout() {
        // 1. SecurityContextHolder 中的用户对象
        UsernamePasswordAuthenticationToken authenticationToken =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authenticationToken.getPrincipal();
        if (Objects.isNull(loginUser)) {
            throw new CustomLoginException();
        }
        User user = loginUser.getUser();

        // 2. 获取用户id
        String userId = user.getId().toString();

        // 3. 删除 redis 中的值
        redisCache.deleteObject(RedisKey.userKey + userId);

        return ResponseResult.success(httpStatusDescriptions.getDescription(HttpStatus.OK));
    }

    /**
     * 用户登录接口
     * @param user 用户对象, 获取用户名和密码
     * @return 返回结果
     */
    @Override
    public ResponseResult<?> login(User user) {
        // 获取 AuthenticationManager 的 authenticate 方法进行认证
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
        Authentication authenticate = authentication.authenticate(authenticationToken);

        if (Objects.isNull(authenticate)) {
            // 认证不通过
            throw new RuntimeException("登录失败!");
        }
        // 认证通过, 生成 jwt, 否则直接返回
        // 获取用户对象
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        // 生成 jwt
        User userInfo = loginUser.getUser();
        String userId = userInfo.getId().toString();
        String userType = userInfo.getUserType();

        HashMap<String , Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("userType", userType);
        String token = JwtUtil.createJWT(map, user.getJwtId());

        // 将 token 存入 redis
        loginUser.setJwtId(user.getJwtId());
        redisCache.setCacheObject(RedisKey.userKey + userId, loginUser);

        HashMap<String, Object> result = new HashMap<>();
        result.put("userId", userId);
        result.put("userType", userType);
        result.put("token", token);
        return ResponseResult.success(result);
    }
}
